package city.spring.modules.work.controller;

import city.spring.modules.system.mapstruct.SimpleUserVoMapStruct;
import city.spring.modules.system.service.UserService;
import city.spring.modules.system.vo.SimpleUserVO;
import city.spring.modules.work.entity.WorkShiftRecordEntity;
import city.spring.modules.work.service.WorkShiftRecordService;
import city.spring.modules.work.vo.WorkShiftRecordVO;
import city.spring.utils.BeanUtils;
import city.spring.utils.MyBatisUtils;
import city.spring.utils.OrganizationUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.api.ApiController;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Controller：工作交接班记录、交班记录
 *
 * @author 侯坤林
 * @date 2020-09-09 14:39:16
 */
@RestController
@RequestMapping("/work_shift_record")
public class WorkShiftRecordController extends ApiController {
    private final WorkShiftRecordService workShiftRecordService;
    private final UserService userService;
    private final SimpleUserVoMapStruct simpleUserVoMapStruct;
    /**
     * 实体类可排序字段
     */
    private final List<SFunction<WorkShiftRecordEntity, ?>> entityOrderFields;

    public WorkShiftRecordController(WorkShiftRecordService workShiftRecordService, UserService userService, SimpleUserVoMapStruct simpleUserVoMapStruct) {
        this.workShiftRecordService = workShiftRecordService;
        this.userService = userService;
        this.simpleUserVoMapStruct = simpleUserVoMapStruct;
        entityOrderFields = new ArrayList<>();
        entityOrderFields.add(WorkShiftRecordEntity::getId);
        entityOrderFields.add(WorkShiftRecordEntity::getCurrentOrgId);
        entityOrderFields.add(WorkShiftRecordEntity::getArea);
        entityOrderFields.add(WorkShiftRecordEntity::getDate);
        entityOrderFields.add(WorkShiftRecordEntity::getPeopleNum);
        entityOrderFields.add(WorkShiftRecordEntity::getExceptionText);
        entityOrderFields.add(WorkShiftRecordEntity::getLeaveHospital);
        entityOrderFields.add(WorkShiftRecordEntity::getCheckIn);
        entityOrderFields.add(WorkShiftRecordEntity::getGoOutSeeDoctor);
        entityOrderFields.add(WorkShiftRecordEntity::getTransferOut);
        entityOrderFields.add(WorkShiftRecordEntity::getTransferIn);
        entityOrderFields.add(WorkShiftRecordEntity::getDayPreUserId);
        entityOrderFields.add(WorkShiftRecordEntity::getDayNextUserId);
        entityOrderFields.add(WorkShiftRecordEntity::getDayCheckInText);
        entityOrderFields.add(WorkShiftRecordEntity::getDayDeviceText);
        entityOrderFields.add(WorkShiftRecordEntity::getDayOtherText);
        entityOrderFields.add(WorkShiftRecordEntity::getNightPreUserId);
        entityOrderFields.add(WorkShiftRecordEntity::getNightNextUserId);
        entityOrderFields.add(WorkShiftRecordEntity::getNightCheckInText);
        entityOrderFields.add(WorkShiftRecordEntity::getNightDeviceText);
        entityOrderFields.add(WorkShiftRecordEntity::getNightOtherText);
        entityOrderFields.add(WorkShiftRecordEntity::getRemarks);
        entityOrderFields.add(WorkShiftRecordEntity::getGmtCreated);
        entityOrderFields.add(WorkShiftRecordEntity::getGmtModified);
    }

    /**
     * 获取全部的 <strong>工作交接班记录、交班记录</strong> 列表
     */
    @GetMapping("all")
    public Object listAll(@PageableDefault Pageable pageable, WorkShiftRecordEntity entity) {
        LambdaQueryChainWrapper<WorkShiftRecordEntity> lambdaQuery = buildLambdaQuery(entity);
        OrganizationUtils.includes(lambdaQuery, WorkShiftRecordEntity::getCurrentOrgId);
        MyBatisUtils.lambdaQueryAddOrder(lambdaQuery, pageable, entityOrderFields);
        return success(lambdaQuery.list());
    }

    /**
     * 分页获取 <strong>工作交接班记录、交班记录</strong> 列表
     *
     * @param pageable 分页参数信息
     */
    @GetMapping
    public Object list(@PageableDefault Pageable pageable, WorkShiftRecordEntity entity) {
        LambdaQueryChainWrapper<WorkShiftRecordEntity> lambdaQuery = buildLambdaQuery(entity);
        OrganizationUtils.includes(lambdaQuery, WorkShiftRecordEntity::getCurrentOrgId);
        MyBatisUtils.lambdaQueryAddOrder(lambdaQuery, pageable, entityOrderFields);
        Page<WorkShiftRecordEntity> page = lambdaQuery.page(MyBatisUtils.toPage(pageable, false));
        List<WorkShiftRecordEntity> records = page.getRecords();
        // 收集所有的用户ID
        Set<String> userIds = new HashSet<>();
        for (WorkShiftRecordEntity record : records) {
            userIds.add(record.getDayPreUserId());
            userIds.add(record.getDayNextUserId());
            userIds.add(record.getNightPreUserId());
            userIds.add(record.getNightNextUserId());
        }
        // 查出这些用户ID对应的人员信息
        Map<String, SimpleUserVO> userEntityMap = null;
        if (userIds.isEmpty()) {
            userEntityMap = new HashMap<>();
        } else {
            userEntityMap = userService.listByIds(userIds)
                    .stream()
                    // 把完整的用户信息对象转换为简单的用户信息对象（只包含一部分信息）
                    .map(simpleUserVoMapStruct::toVo)
                    // 以用户ID为key，用户信息对象为Value存入到map对象中
                    .collect(Collectors.toMap(SimpleUserVO::getId, Function.identity()));
        }
        // 把处理后的用户信息放入返回结果中
        List<WorkShiftRecordEntity> workShiftRecordEntities = new ArrayList<>();
        for (WorkShiftRecordEntity record : records) {
            WorkShiftRecordVO vo = BeanUtils.toChildren(record, WorkShiftRecordVO.class);
            vo.setDayPreUser(userEntityMap.get(vo.getDayPreUserId()));
            vo.setDayNextUser(userEntityMap.get(vo.getDayNextUserId()));
            vo.setNightPreUser(userEntityMap.get(vo.getNightPreUserId()));
            vo.setNightNextUser(userEntityMap.get(vo.getNightNextUserId()));
            workShiftRecordEntities.add(vo);
        }
        page.setRecords(workShiftRecordEntities);
        return success(page);
    }

    /**
     * 获取一个 <strong>工作交接班记录、交班记录</strong>
     *
     * @param id 主键ID
     */
    @GetMapping("{id}")
    public Object info(@PathVariable String id) {
        return success(workShiftRecordService.getById(id));
    }

    /**
     * 添加一个 <strong>工作交接班记录、交班记录</strong>
     *
     * @param entity 修改后的信息
     */
    @PostMapping
    public Object add(@RequestBody WorkShiftRecordEntity entity) {
        workShiftRecordService.saveWorkShiftRecord(entity);

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.LOCATION, String.valueOf(entity.getId()));
        return new ResponseEntity<>(headers, HttpStatus.CREATED);
    }

    /**
     * 修改一个 <strong>工作交接班记录、交班记录</strong>
     *
     * @param id     主键ID
     * @param entity 修改后的信息
     */
    @PutMapping("{id}")
    public Object update(@PathVariable String id, @RequestBody WorkShiftRecordEntity entity) {
        entity.setId(id);
        workShiftRecordService.updateWorkShiftRecord(entity);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 删除一个 <strong>工作交接班记录、交班记录</strong>
     *
     * @param id 主键ID
     */
    @DeleteMapping("{id}")
    public Object delete(@PathVariable String id) {
        workShiftRecordService.deleteWorkShiftRecord(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    /**
     * 删除多个 <strong>工作交接班记录、交班记录</strong>
     *
     * @param ids 主键ID列表
     */
    @DeleteMapping
    public Object deleteIds(@RequestBody List<String> ids) {
        workShiftRecordService.deleteWorkShiftRecord(ids);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    /**
     * 构建查询条件内容
     *
     * @param entity 实体对象
     * @return lambda query chain wrapper
     */
    private LambdaQueryChainWrapper<WorkShiftRecordEntity> buildLambdaQuery(WorkShiftRecordEntity entity) {
        LambdaQueryChainWrapper<WorkShiftRecordEntity> lambdaQuery = workShiftRecordService.lambdaQuery();
        lambdaQuery.eq(StringUtils.isNotBlank(entity.getId()), WorkShiftRecordEntity::getId, entity.getId());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getCurrentOrgId()), WorkShiftRecordEntity::getCurrentOrgId, entity.getCurrentOrgId());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getArea()), WorkShiftRecordEntity::getArea, entity.getArea());
        lambdaQuery.eq(entity.getDate() != null, WorkShiftRecordEntity::getDate, entity.getDate());
        lambdaQuery.eq(entity.getPeopleNum() != null, WorkShiftRecordEntity::getPeopleNum, entity.getPeopleNum());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getExceptionText()), WorkShiftRecordEntity::getExceptionText, entity.getExceptionText());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getLeaveHospital()), WorkShiftRecordEntity::getLeaveHospital, entity.getLeaveHospital());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getCheckIn()), WorkShiftRecordEntity::getCheckIn, entity.getCheckIn());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getGoOutSeeDoctor()), WorkShiftRecordEntity::getGoOutSeeDoctor, entity.getGoOutSeeDoctor());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getTransferOut()), WorkShiftRecordEntity::getTransferOut, entity.getTransferOut());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getTransferIn()), WorkShiftRecordEntity::getTransferIn, entity.getTransferIn());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getDayPreUserId()), WorkShiftRecordEntity::getDayPreUserId, entity.getDayPreUserId());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getDayNextUserId()), WorkShiftRecordEntity::getDayNextUserId, entity.getDayNextUserId());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getDayCheckInText()), WorkShiftRecordEntity::getDayCheckInText, entity.getDayCheckInText());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getDayDeviceText()), WorkShiftRecordEntity::getDayDeviceText, entity.getDayDeviceText());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getDayOtherText()), WorkShiftRecordEntity::getDayOtherText, entity.getDayOtherText());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getNightPreUserId()), WorkShiftRecordEntity::getNightPreUserId, entity.getNightPreUserId());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getNightNextUserId()), WorkShiftRecordEntity::getNightNextUserId, entity.getNightNextUserId());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getNightCheckInText()), WorkShiftRecordEntity::getNightCheckInText, entity.getNightCheckInText());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getNightDeviceText()), WorkShiftRecordEntity::getNightDeviceText, entity.getNightDeviceText());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getNightOtherText()), WorkShiftRecordEntity::getNightOtherText, entity.getNightOtherText());
        lambdaQuery.like(StringUtils.isNotBlank(entity.getRemarks()), WorkShiftRecordEntity::getRemarks, entity.getRemarks());
        lambdaQuery.eq(entity.getGmtCreated() != null, WorkShiftRecordEntity::getGmtCreated, entity.getGmtCreated());
        lambdaQuery.eq(entity.getGmtModified() != null, WorkShiftRecordEntity::getGmtModified, entity.getGmtModified());
        return lambdaQuery;
    }

    /**
     * 构建查询条件内容
     *
     * @param entity 实体对象
     * @return lambda query chain wrapper
     */
    private QueryWrapper<WorkShiftRecordEntity> buildQuery(WorkShiftRecordEntity entity) {
        QueryWrapper<WorkShiftRecordEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(entity.getId()), "id", entity.getId());
        wrapper.like(StringUtils.isNotBlank(entity.getCurrentOrgId()), "current_org_id", entity.getCurrentOrgId());
        wrapper.like(StringUtils.isNotBlank(entity.getArea()), "area", entity.getArea());
        wrapper.eq(entity.getDate() != null, "date", entity.getDate());
        wrapper.eq(entity.getPeopleNum() != null, "people_num", entity.getPeopleNum());
        wrapper.like(StringUtils.isNotBlank(entity.getExceptionText()), "exception_text", entity.getExceptionText());
        wrapper.like(StringUtils.isNotBlank(entity.getLeaveHospital()), "leave_hospital", entity.getLeaveHospital());
        wrapper.like(StringUtils.isNotBlank(entity.getCheckIn()), "check_in", entity.getCheckIn());
        wrapper.like(StringUtils.isNotBlank(entity.getGoOutSeeDoctor()), "go_out_see_doctor", entity.getGoOutSeeDoctor());
        wrapper.like(StringUtils.isNotBlank(entity.getTransferOut()), "transfer_out", entity.getTransferOut());
        wrapper.like(StringUtils.isNotBlank(entity.getTransferIn()), "transfer_in", entity.getTransferIn());
        wrapper.like(StringUtils.isNotBlank(entity.getDayPreUserId()), "day_pre_user_id", entity.getDayPreUserId());
        wrapper.like(StringUtils.isNotBlank(entity.getDayNextUserId()), "day_next_user_id", entity.getDayNextUserId());
        wrapper.like(StringUtils.isNotBlank(entity.getDayCheckInText()), "day_check_in_text", entity.getDayCheckInText());
        wrapper.like(StringUtils.isNotBlank(entity.getDayDeviceText()), "day_device_text", entity.getDayDeviceText());
        wrapper.like(StringUtils.isNotBlank(entity.getDayOtherText()), "day_other_text", entity.getDayOtherText());
        wrapper.like(StringUtils.isNotBlank(entity.getNightPreUserId()), "night_pre_user_id", entity.getNightPreUserId());
        wrapper.like(StringUtils.isNotBlank(entity.getNightNextUserId()), "night_next_user_id", entity.getNightNextUserId());
        wrapper.like(StringUtils.isNotBlank(entity.getNightCheckInText()), "night_check_in_text", entity.getNightCheckInText());
        wrapper.like(StringUtils.isNotBlank(entity.getNightDeviceText()), "night_device_text", entity.getNightDeviceText());
        wrapper.like(StringUtils.isNotBlank(entity.getNightOtherText()), "night_other_text", entity.getNightOtherText());
        wrapper.like(StringUtils.isNotBlank(entity.getRemarks()), "remarks", entity.getRemarks());
        wrapper.eq(entity.getGmtCreated() != null, "gmt_created", entity.getGmtCreated());
        wrapper.eq(entity.getGmtModified() != null, "gmt_modified", entity.getGmtModified());
        return wrapper;
    }

}
